//+---------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation, 2005
//
// File: BaseException.cs
//
// Contents: Exception class for wrapping exceptions and providing goood error
//           messages.
//
// Created by: adamland 2/18/2005
//
//----------------------------------------------------------------------------

using System;
using System.Text;
using System.Runtime.Serialization;

namespace Microsoft.Reputation.Services
{
    [Serializable]
    public class BaseException : Exception
    {
        protected BaseExceptionContext m_context = null;
        
        public static BaseException Create(
            string errorString, 
            string operationString, 
            string objectString)
        {
            using (TraceUtility.TraceMethod(Tracing.Source, "errorString={0}, operationString={1}, objectString={2}", errorString, operationString, objectString))
            {
                BaseExceptionContext context = new BaseExceptionContext(errorString, operationString, objectString);
                
                return new BaseException(context);
            }
        }

        /// <summary>
        /// Constructs a BaseException.
        /// </summary>
        /// <param name="ex">Inner exception, and source of the error message string</param>
        /// <param name="operationString">Operation string</param>
        /// <param name="objectString">Object string</param>
        /// <returns></returns>
        public static BaseException Create(
            Exception ex,
            string operationString,
            string objectString)
        {
            TraceUtility.TraceAssert(Tracing.Source, ex != null, "Passed null exception");

            using (TraceUtility.TraceMethod(Tracing.Source, "ex.Message={0}, operationString={1}, objectString={2}", ex.Message, operationString, objectString))
            {
                BaseExceptionContext context = new BaseExceptionContext(
                    ex == null ? string.Empty : ex.Message,
                    operationString,
                    objectString);

                return new BaseException(ex, context);
            }
        }

        private BaseException()
        {
        }

        public BaseException(BaseExceptionContext context) : base()
        {
            m_context = context;
        }

        public BaseException(Exception ex) : base(string.Empty, ex)
        {
            TraceUtility.TraceAssert(Tracing.Source, ex != null, "Passed null exception");

            BaseException baseException = ex as BaseException;
            
            if (baseException == null)
            {
                m_context = new BaseExceptionContext(ex == null ? string.Empty : ex.Message);
            }
            else
            {
                m_context = baseException.m_context;
            }
        }

        public BaseException(
            Exception ex,
            BaseExceptionContext context) : base(string.Empty, ex)
        {
            BaseException baseException = ex as BaseException;

            TraceUtility.TraceAssert(
                Tracing.Source,
                baseException == null,
                "The inner exception should not be a BaseException when providing a new BaseExceptionContext");

            m_context = context;
        }

        protected BaseException(
            SerializationInfo serializationInfo, 
            StreamingContext streamingContext) : base(serializationInfo, streamingContext)
        {
        }

        public override string Message
        {
            get
            {
                //TraceUtility.TraceAssert(Tracing.Source, false, "BaseExceptions have no Message. Use ToString");
                return ToString();
            }
        }
        
        public BaseExceptionContext Context
        {
            get
            {
                return m_context;
            }
        }

        public override string ToString()
        {
            return ToString("\r\n");
        }

        public virtual string ToString(string delimiter)
        {
            TraceUtility.TraceAssert(Tracing.Source, m_context != null);

            return m_context.BuildMessage();
        }
    } 
}
